package gov.dhs.cis.soa.readers.reqpro;

import gov.dhs.cis.soa.Constants;
import gov.dhs.cis.soa.SOAData;
import gov.dhs.cis.soa.Utils;
import gov.dhs.cis.soa.Constants.EntityType;
import gov.dhs.cis.soa.data.Actor;
import gov.dhs.cis.soa.data.UseCase;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Set;

import org.apache.log4j.Logger;

import com.rational.reqpro.rpx.Application;
import com.rational.reqpro.rpx.AttrValue;
import com.rational.reqpro.rpx._Application;
import com.rational.reqpro.rpx._AttrValues;
import com.rational.reqpro.rpx._Errors;
import com.rational.reqpro.rpx._Project;
import com.rational.reqpro.rpx._Requirement;
import com.rational.reqpro.rpx._Requirements;
import com.rational.reqpro.rpx.enumListItemValueLookups;
import com.rational.reqpro.rpx.enumOpenProjectOptions;
import com.rational.reqpro.rpx.enumProjectFlags;
import com.rational.reqpro.rpx.enumRelatedProjectOptions;
import com.rational.reqpro.rpx.enumRequirementFlags;
import com.rational.reqpro.rpx.enumRequirementLookups;
import com.rational.reqpro.rpx.enumRequirementsWeights;
import com.rational.reqpro.rpx.enumTagFormat;
import com.rational.rjcb.ComObjectProxy;

public class RolesReader {
	static final Logger loger = Logger.getLogger(RolesReader.class);
	HashMap<String, Actor> kindOf = null;
	HashMap<String, Actor> personas = null;
	
	public SOAData extractRoles(SOAData soaData) {
		_Application RPX = null;
		try {
			RPX = new Application();
			_Project project = RPX.OpenProject(Constants.REQPRO_PROJECT,
					enumOpenProjectOptions.eOpenProjOpt_RQSFile, Constants.REQPRO_USER,
					Constants.REQPRO_PASS, enumProjectFlags.eProjFlag_Normal,
					enumRelatedProjectOptions.eRelatedProjOption_ConnectNone);
			_Requirements requs = project.GetRequirements("RL", enumRequirementLookups.eReqLookup_Tag, 
					enumRequirementsWeights.eReqWeight_Medium, enumRequirementFlags.eReqFlag_Empty,
					100, 40);
			int reqCount = requs.getCount();
			System.out.println("Roles Count : " + reqCount);
			int ucCount = 0;
			ArrayList<Actor> actorsList = new ArrayList<Actor>();
			soaData.actorList = actorsList;

			kindOf = new HashMap<String, Actor>();
			personas = new HashMap<String, Actor>();
			
			if(reqCount > 0) {
				requs.MoveFirst();
				_Requirement req = null;
				for(int i = 0; i < reqCount; i++) {
					req = requs.GetCurrentRequirement();
					if(req.getLevel() == 0) {
						ucCount++;
						createActorFromRequirement(req, actorsList);
					}
					requs.MoveNext();
				}
			}
			System.out.println("Total Roles count : " + ucCount);
			
			project.CloseProject();
			ComObjectProxy obj = (ComObjectProxy) RPX;
			obj.release();
			RPX= null;			
		} catch (Exception e) {
			try {
				_Errors err = RPX.getErrors();
				System.out.println(err.getAllMessages());
				e.printStackTrace();
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}				
		} finally {
		}
		return soaData;
	}

	private Actor getRequirementAttrs(ArrayList<Actor> actorsList, Actor u, _Requirement req) throws Exception {
		_AttrValues types = req.getAttrValues();
		int count = types.getCount();
		if(count <= 0)
			return u;
		//System.out.println("RequirementAttrs# :" + count);
		Enumeration e = types.NewEnum();
		String value = null;
		while(e.hasMoreElements()) {
			AttrValue type = new AttrValue(e.nextElement());
			//System.out.println(type.getLabel() + " : " + type.getText());
			if("Type".equalsIgnoreCase(type.getLabel())) {
				value = null;
				if(type.getSelectedListItemValue() != null)
					value = type.getSelectedListItemValue().getText();
				if("Human".equalsIgnoreCase(value)) {
					u.roleType = Actor.HUMAN_ROLE_TYPE;
				} else if("External System".equalsIgnoreCase(value)) {
					u.roleType = Actor.SYSTEM_ROLE_TYPE;
				} else {
					u.roleType = "";
				}
			} else if("Actor".equalsIgnoreCase(type.getLabel())) {
				value = null;
				if(type.getSelectedListItemValue() != null)
					value = type.getSelectedListItemValue().getText();
				if("True".equalsIgnoreCase(value))
					u.isActor = "Y";
				else
					u.isActor = "N";
			} else if("Kind of".equalsIgnoreCase(type.getLabel())) {
				value = null;
				if(type.getSelectedListItemValue() != null)
					value = type.getSelectedListItemValue().getText();
				if(Utils.isEmpty(value)) {
					System.out.println("Skipping <Kind of> for : " + u.name);
				} else {
					Actor t = kindOf.get(value); 
					if(t == null) {
						t = createActor(value, Actor.HUMAN_ROLE_TYPE, value);
						kindOf.put(value, t);
						actorsList.add(t);
					}
					t.addChildActor(u);
				}
			} else if("Persona Group".equalsIgnoreCase(type.getLabel())) {
				value = null;
				if(type.getSelectedListItemValue() != null)
					value = type.getSelectedListItemValue().getText();
				if(Utils.isEmpty(value)) {
					System.out.println("Skipping <Persona Group> for : " + u.name);
				} else {
					Actor t = personas.get(value); 
					if(t == null) {
						t = createActor(value, Actor.PERSONA_ROLE_TYPE, value);
						personas.put(value, t);
						actorsList.add(t);
					}
					u.persona = t;
				}
			} else if("Obsolete".equalsIgnoreCase(type.getLabel())) {
				value = type.getText();
				if("True".equalsIgnoreCase(value))
					return null;
			}
		}
		return u;
	}


	public Actor createActorFromRequirement(_Requirement req, ArrayList<Actor> actorsList) throws Exception {
		Actor act = Utils.findActorByName(req.getName(), actorsList);
		boolean bActFound = (act != null);
		if(!bActFound)
			act = createActor(req.getName(), Actor.HUMAN_ROLE_TYPE, req.getTag(enumTagFormat.eTagFormat_FullTag));
		act = getRequirementAttrs(actorsList, act, req);
		if(act != null && !bActFound)
			actorsList.add(act);
		return act;
	}	

	public Actor createActor(String name, String role, String desc) {
		Actor actor = new Actor();
		actor.id = Utils.getNextId();
		actor.name = name;
		actor.desc = Utils.prepareDescObj(desc, EntityType.ACTR);
		actor.roleType = role;
		return actor;
	}
	
	/**may be dev 
	 * @param args
	 */
	public static void main(String[] args) {
		RolesReader pr = new RolesReader();
		try {
			SOAData sData = new SOAData();
			pr.extractRoles(sData);
			System.out.println("Done");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
